package jp.sourceforge.talisman.mds;

/*
 * $Id: Item.java,v 1.1 2009/09/12 05:06:20 weiwei Exp $
 */

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

/**
 * 
 * @author Haruaki Tamada
 * @version $Revision: 1.1 $
 */
public class Item implements Iterable<Number>{
    private List<Number> numbers = new ArrayList<Number>();
    private String name;
    private int limit = -1;
    private int groupId = 0;

    /**
     * self constructor
     */
    public Item(Item item){
        if(item == null){
            throw new NullPointerException();
        }
        setName(item.getName());
        setGroupId(item.getGroupId());
        for(Number number: item){
            add(number);
        }
        if(item.isLimitted()){
            setLimit(item.getDimension());
        }
    }

    public Item(String label, double[] values){
        this(label);
        for(int i = 0; i < values.length; i++){
            add(i, values[i]);
        }
    }

    public Item(String label, int dimension){
        this(label);
        for(int i = 0; i < dimension; i++){
            add(i, 0);
        }
    }

    public Item(String label){
        setName(label);
    }

    public void add(int index, Number number){
        if(isLimitted() && index >= getDimension()){
            throw new IndexOutOfBoundsException(String.format("out of range: %d >= %d", index, getDimension()));
        }
        numbers.add(index, number);
    }

    public void add(Number number){
        numbers.add(number);
    }

    public Number get(int index){
        if(isLimitted() && index >= getDimension()){
            throw new IndexOutOfBoundsException(String.format("out of range: %d >= %d", index, getDimension()));
        }
        return numbers.get(index);
    }

//    public void set(int index, Number number){
//        if(isLimitted() && index >= getDimension()){
//            throw new IndexOutOfBoundsException(String.format("out of range: %d >= %d", index, getDimension()));
//        }
//        numbers.set(index, number);
//    }

    public void remove(int index){
        if(isLimitted() && index >= getDimension()){
            throw new IndexOutOfBoundsException(String.format("out of range: %d >= %d", index, getDimension()));
        }
        numbers.remove(index);
    }

    public int getGroupId(){
        return groupId;
    }

    public String getName(){
        return name;
    }

    public void setLimit(int limit){
        if(limit <= 0){
            throw new IllegalArgumentException("positive value required: " + limit);
        }
        this.limit = limit;
    }

    public boolean isLimitted(){
        return limit > 0;
    }

    public void removeLimit(){
        limit = -1;
    }

    public int getDimension(){
        if(isLimitted()){
            if(limit < numbers.size()){
                return limit;
            }
        }
        return numbers.size();
    }

    public int getNonLimittedDimension(){
        return numbers.size();
    }

    public Iterator<Number> iterator(){
        return new ArrayList<Number>(numbers).iterator();
    }

    public void setGroupId(int groupId){
        this.groupId = groupId;
    }

    public void setName(String label){
        if(label == null){
            throw new NullPointerException();
        }
        this.name = label;
    }

    public boolean equals(Object o){
        if(o instanceof Item){
            Item item = (Item)o;
            boolean flag = item.getDimension() == getDimension();
            for(int i = 0; i < getDimension(); i++){
                flag = flag && Math.abs(item.get(i).doubleValue() - get(i).doubleValue()) < 1E-6;
                if(!flag){
                    break;
                }
            }
            return flag;
        }
        return false;
    }

    public boolean isSame(Item item){
        if(equals(item)){
            return getName().equals(item.getName()) && getGroupId() == item.getGroupId();
        }
        return false;
    }

    public synchronized String toString(){
        return toString(getDimension());
    }

    public synchronized String toString(int limits){
        StringBuilder sb = new StringBuilder(getName());
        sb.append("[").append(getGroupId()).append("] (");
        for(int i = 0; i < limits || i < getDimension(); i++){
            if(i != 0){
                sb.append(", ");
            }
            Number num = get(i);
            String format = "%d";
            if(num instanceof Float || num instanceof Double || num instanceof BigDecimal){
                format = "%g";
            }
            sb.append(String.format(format, get(i)));
        }
        sb.append(")");

        return new String(sb);
    }
}
